from .error_code import ErrCode
from tuntun.settings import APP_DOWNLOAD_LINK
from apps.message.views import *
from common.exceptions import (JsonAPIException,
                               ParametersErrorAPIException)
from common import time_rest, int_2_2d
from tuntun.settings import PAY_EXPIRE_TIME
from apps.mix.tasks import *
from apps.system.models import SystemSetting
from apps.mix.tasks import *
import datetime
import time
from tuntun.settings import NORMAL_USER_PRE_SALE_ORDER_LIMIT
from apps.repo.models import Repo
from django.core.paginator import Paginator
import traceback


# Create your views here.

def val(offset, limit):
    """
    检验参数
    :param offset:
    :param limit:
    :return:
    """
    try:
        offset = int(offset)
        limit = int(limit)
    except:
        raise JsonAPIException(ErrCode.PAGE_ARG_ERROR.name, "页码参数错误", errors=[])
    return offset, limit


def is_Decimal(price):
    try:
        re_price = Decimal(price)
        return re_price
    except:
        raise JsonAPIException(ErrCode.PRICE_ERROR.name, ErrCode.PRICE_ERROR.value)


class ListIndexBannerView(BaseAPIView):
    """
    首页轮播列表
    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        """Get"""
        resp = {}
        count, objs = IndexBanner.objects.filter_by_page(-1, -1)  # type: []
        resp['count'] = count
        resp['items'] = []
        for obj in objs:
            print(obj)
            resp['items'].append({
                'img_url': obj.image_url,
                'link': obj.link,
            })
        print(resp)
        return Response(resp)


class GetPreSaleListView(BaseAPIView):
    """
    预售产品
    filter:
        unfolded    未折叠的预售产品（首页显示），此时忽略分页参数
        all         显示所有
    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        import datetime
        now = datetime.datetime.now()
        resp = {"count": 0, "items": []}
        offset = request.GET.get('offset', 0)
        limit = request.GET.get('limit', 0)
        offset, limit = val(offset, limit)

        if limit == 0:
            return Response(resp)

        filter = kwargs['filter']
        if filter == "unfolded":
            tmp_products = Product.objects.filter(is_unfolded=True, status='PRE_SALE_ING', pre_sale_end_time__gt=now)
        else:
            tmp_products = Product.objects.filter(status='PRE_SALE_ING',pre_sale_end_time__gt=now)

        products = []
        for p in tmp_products:
            if p.stock > 0:
                products.append(p)

        count = len(products)
        objs = []
        if offset == -1 and limit == -1:
            objs = products
        else:
            try:
                paginator = Paginator(products, limit)
                req_page = offset // limit + 1
                objs = paginator.page(req_page).object_list
            except:
                count = 0
                objs = []

        resp['count'] = count
        for product in objs:
            resp['items'].append(product.product_detail())
        return Response(resp)


class DetailProductView(BaseAPIView):
    """
    商品详情
     GET     /product/products/:id
    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        import datetime
        product_id = kwargs['id']
        if product_id == "":
            raise JsonAPIException(ErrCode.PARAMETER_EMPTY.name, ErrCode.PARAMETER_EMPTY.value)
        product = Product.objects.filter(id=product_id)
        if product.count() != 0:
            pro = product[0]
            repo = Repo.objects.filter(id=pro.repo_id)[0]
            images = ProductLongImage.objects.filter(product_id=pro.id).order_by("order")
            images_url = []
            for img in images:
                images_url.append({
                    "img_url": img.banner_url
                })
            pre_sale_rest_times = pro.pre_sale_end_time - datetime.datetime.now()
            tr = time_rest(pre_sale_rest_times.total_seconds())
            res = {
                "logo": pro.logo,
                "name": pro.name,
                "brand_id": pro.brand.id,
                "brand": pro.brand.name,
                "brand_logo": pro.brand.logo,
                "brand_attention_count": pro.brand.attention_count.__str__(),
                "store_id": pro.brand.store.id,
                "store": pro.brand.store.name,
                "stock": pro.stock.__str__(),
                "pre_sale_price": pro.pre_sale_price.__str__(),
                "pre_sale_start_end": '%s-%s' % (
                    pro.pre_sale_start_time.strftime('%Y.%m.%d'), pro.pre_sale_end_time.strftime('%m.%d')),
                "pre_sale_rest_times": "%s天%s时%s分" % (int_2_2d(tr.days), int_2_2d(tr.hours), int_2_2d(tr.minutes)),
                "id": pro.id,
                "video_banner": pro.video,
                "specification": pro.specification,
                "kind": pro.kind,
                "material": pro.material,
                "repo": repo.name,
                "age": pro.age,
                "publish_count": pro.publish_count.__str__(),
                "technology": pro.technology,
                "tea_mountain": pro.tea_mountain,
                "altitude": pro.altitude.__str__(),
                "ancient_tea_tree_count": pro.ancient_tea_tree_count.__str__(),
                "year_avg_temperature": pro.year_avg_temperature,
                "year_avg_precipitation": pro.year_avg_precipitation,
                "made_in": pro.made_in,
                "long_images": images_url,
                "status": pro.status,
                "status_map": dict(Product.ProductStatus.get_choices()),
                "keeping_count": pro.keeping_count.__str__(),
                "avg_price": pro.avg_price_custom.__str__(),
                "up_down_percent": pro.up_down_percent.__str__(),
                "order_limit": NORMAL_USER_PRE_SALE_ORDER_LIMIT.__str__() if not isinstance(request.user, User) else request.user.get_pre_sale_order_limit(pro.id),
            }
            return Response(res, status=status.HTTP_200_OK)
        else:
            return Response({
                "code": ErrCode.RETURN_EMPTY.name,
                "msg": ErrCode.RETURN_EMPTY.value
            }, status=status.HTTP_200_OK)


class DetailBrandView(BaseAPIView):
    """
    品牌故事详情
    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        id = kwargs['id']
        print(id)
        brand = Brand.objects.get(pk=id)
        if brand:
            return Response({
                "download_link": APP_DOWNLOAD_LINK,
                "name": brand.name,
                "logo": brand.logo,
                "attention_count": brand.attention_count,
                "store_id": brand.store_id,
                "store": brand.store.name,
                "store_type": brand.store.store_type,
                "id": brand.id,
                "video_banner": brand.video,
                "long_images": [
                    {
                        "img_url": li.logo
                    }
                    for li in BrandLongImage.objects.filter(brand=brand).order_by('order')
                ]
            })
        else:
            raise JsonAPIException(ErrCode.RETURN_EMPTY.name, ErrCode.RETURN_EMPTY.value, [])


class DetailStoreView(BaseAPIView):
    """
    茶庄详情
    发现/详情页/茶庄
    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        id = kwargs['id']
        store = Store.objects.filter(pk=id).first()

        if store:
            data = {
                "name": store.name,
                "store_type": store.store_type,
                "video_banner": store.video,
                "long_images": [
                    {
                        "img_url": li.logo,
                    }
                    for li in StoreBanner.objects.filter(store=store).order_by('order')
                ],
                "store_type_map": {
                    "GROWER": "茶农茶庄",
                    "BRAND": "品牌茶庄"
                },
            }
            return Response(data)
        else:
            raise JsonAPIException(ErrCode.RETURN_EMPTY.name, ErrCode.RETURN_EMPTY.value, [])


class GetIndexBrandListView(BaseAPIView):
    """
    首页品牌列表
    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        offset = request.GET.get('offset', "")
        limit = request.GET.get('limit', "")
        offset, limit = val(offset, limit)

        resp = {"count": 0, "items": []}

        if limit == 0:
            return Response(resp)

        count, brand_list = Brand.objects.filter_by_page(offset, limit)
        resp['count'] = count
        for brand in brand_list:
            resp['items'].append({
                "id": brand.id,
                "name": brand.name,
                "logo": brand.logo,
                "attention_count": brand.attention_count,
                "is_attention": brand.is_attention(user_id=request.user.id)
            })
        return Response(resp, status=status.HTTP_200_OK)


class GetBrandProductListView(BaseAPIView):
    """
    品牌下的产品列表
    """

    permission_classes = ()

    def get(self, request, *args, **kwargs):
        brand_id = kwargs['brand_id']
        offset = request.GET.get('offset', "-1")
        limit = request.GET.get('limit', "-1")
        offset, limit = val(offset, limit)
        resp = {"count": 0, "items": [], "brand_is_attention": False}
        if limit == 0:
            return Response(resp)
        count, product_list = Product.objects.filter_by_page(int(offset), int(limit), brand_id=brand_id,
                                                             status__in=(Product.ProductStatus.PRE_SALE_ING.name,
                                                                         Product.ProductStatus.PRE_SALE_END.name))
        brand = Brand.objects.filter(id=brand_id).first()
        print(count, product_list)
        resp['count'] = count
        resp['brand_is_attention'] = brand.is_attention(request.user.id)
        resp['brand_attention_count'] = brand.attention_count
        for product in product_list:
            tmp = product.product_detail()
            if MarketOrder.objects.filter(product=product, status=MarketOrder.Status.ING.name):
                tmp['have_market_order'] = True
            else:
                tmp['have_market_order'] = False
            resp['items'].append(tmp)

        return Response(resp, status=status.HTTP_200_OK)


class DetailGoodsBlockView(BaseAPIView):
    """
    区块链信息
    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):

        block_id = kwargs["id"]
        if block_id == "":
            raise JsonAPIException(ErrCode.PARAMETER_EMPTY.name, ErrCode.PARAMETER_EMPTY.value, [])

        block_detail = GoodsBlock.objects.filter(id=block_id).first()  # 查询区块信息ID
        if not block_detail:
            block_detail = GoodsBlock.objects.filter(unique_code=block_id).first()  # 按唯一码查询

        good_list = []
        if block_detail:
            goods = GoodsBlockChain.objects.filter(goods_block_id=block_detail.id).order_by("-node_datetime")  # 区块链列表

            for good in goods:
                good_list.append(good.get_block_chain_node_outputs())
            days = (goods.first().node_datetime - goods.last().node_datetime).days + 1

            tpd = block_detail.product.today_price_data
            wpd = block_detail.product.week_price_data
            mpd = block_detail.product.month_price_data

            return Response({
                "id": block_detail.id,
                "unique_code": block_detail.unique_code,
                "product_name": block_detail.product.name,
                "product_keeping_count": block_detail.product.keeping_count,
                "product_avg_price": block_detail.product.avg_price_custom,
                "product_up_down_percent": block_detail.product.up_down_percent,
                "pre_sale_price": block_detail.product.pre_sale_price,
                "last_trade_price": block_detail.product.last_trade_price,
                "today_price_data": tpd,
                "week_price_data": wpd,
                "month_price_data": mpd,
                'app_download_link': APP_DOWNLOAD_LINK,
                'readable_unique_code': block_detail.readable_unique_code,
                "chain": {
                    "days": days,
                    "flows": good_list
                }
            })
        else:
            raise JsonAPIException(ErrCode.RETURN_EMPTY.name, ErrCode.RETURN_EMPTY.value)


class GetTradingProductListView(BaseAPIView):
    """
    交易中的产品列表（发现）

    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        user = request.user
        user_id = ""
        if user:
            user_id = request.user.id
        order = kwargs['order']
        offset = request.GET.get('offset', "")
        limit = request.GET.get('limit', "")

        offset, limit = val(offset, limit)
        resp = {"count": 0, "items": []}
        if limit == 0:
            return Response(resp)

        tmp_market_orders = MarketOrder.objects.filter(status='ING', intention_type=MarketOrder.IntentionType.SELL.name)
        for tmp_market_order in tmp_market_orders:
            if GoodsBlock.objects.filter(market_order=tmp_market_order).count() == 0:
                tmp_market_order.save()
            else:
                tmp_market_order.count = GoodsBlock.objects.filter(market_order=tmp_market_order).count()
                tmp_market_order.save()

        count = MarketOrder.objects.filter(status="ING").values('product').annotate(s_count=Sum('count')).count()
        resp["count"] = count
        # 排序
        order_by = 'product__name'
        if order == "-up_down_percent":
            order_by = '-product__up_down_percent'
        elif order == "up_down_percent":
            order_by = 'product__up_down_percent'

        if offset < 0 or limit < 0:
            market_list = MarketOrder.objects.filter(status=MarketOrder.Status.ING.name,
                                                     publish_type=MarketOrder.PublishType.MARKET.name,
                                                     manzu_ta=False).values(
                'product').order_by(order_by).annotate(s_count=Sum('count'))
        else:
            start_index = offset * limit
            end_index = offset * limit + limit
            market_list = MarketOrder.objects.filter(status=MarketOrder.Status.ING.name,
                                                     publish_type=MarketOrder.PublishType.MARKET.name,
                                                     manzu_ta=False).values(
                'product').order_by(order_by).annotate(s_count=Sum('count'))[start_index:end_index]

        for mar in market_list:
            product = Product.objects.filter(id=mar["product"]).first()

            tpd = product.today_price_data
            wpd = product.week_price_data
            mpd = product.month_price_data

            resp['items'].append({
                "id": product.id,
                "logo": product.logo,
                "name": product.name,
                "brand": product.brand.name,
                "store_id": product.brand.store.id,
                "store": product.brand.store.name,
                "trading_count": mar["s_count"],
                "status": product.status,
                "status_map": dict(Product.ProductStatus.get_choices()),
                "avg_price": product.avg_price_custom.__str__(),
                "up_down_percent": '%d%%' % int(product.up_down_percent * 100),
                "today_price_data": tpd,
                "week_price_data": wpd,
                "month_price_data": mpd,
            })

        return Response(resp)


class DetailTradingProductView(BaseAPIView):
    """
    产品挂单列表  发现/详情页/交易/
======

    GET     /product/tradings/:id/market-orders?action=addtime

URL参数
-----

    id:
        产品ID

Query参数
-------

    action:
        -addtime    按时间倒序
        -offered_price  按价格倒序
        want_buy_in         只显示意向是卖出的，并默认按时间倒序
        satisfy_ta      只显示意向是买入的，并默认按时间排序
    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        product_id = kwargs['id']
        action = request.GET.get("action", '-addtime')
        offset = request.GET.get('offset', "")
        limit = request.GET.get('limit', "")

        offset, limit = val(offset, limit)
        product = Product.objects.filter(id=product_id).first()
        if product == None:
            raise JsonAPIException(ErrCode.RETURN_EMPTY.name, ErrCode.RETURN_EMPTY.value)

        resp = {"count": 0, "items": [], "products": product.product_detail()}
        if limit == 0:
            return Response(resp)

        order_by = "-add_timestamp"
        intention_type = ""
        if action == "addtime":
            order_by = "add_timestamp"
        elif action == "-addtime":
            order_by = "-add_timestamp"
        elif action == "want_buy_in":
            intention_type = "BUY"
        elif action == "satisfy_ta":
            intention_type = "SELL"
        elif "offered_price" in action:
            order_by = action

        if intention_type == "":
            count, market_order = MarketOrder.objects.filter_by_page(offset, limit, status=MarketOrder.Status.ING.name,
                                                                     publish_type=MarketOrder.PublishType.MARKET.name,
                                                                     product_id=product_id,
                                                                     order=order_by, manzu_ta=False)
            resp['count'] = count
        else:
            count, market_order = MarketOrder.objects.filter_by_page(offset, limit, status=MarketOrder.Status.ING.name,
                                                                     publish_type=MarketOrder.PublishType.MARKET.name,
                                                                     intention_type=intention_type,
                                                                     product_id=product_id,
                                                                     order=order_by, manzu_ta=False)
            resp['count'] = count

        for mar in market_order:
            users = User.objects.filter(id=mar.user_id)
            if users.count() > 0:
                user = users[0]
                resp['items'].append({
                    "id": mar.id,
                    "user_id": mar.user_id,
                    "user_nickname": user.nickname,
                    "open_repo": user.open_repo,
                    "user_avatar": user.avatar,
                    "intention_type": mar.intention_type,
                    "intention_type_map": dict(MarketOrder.IntentionType.get_choices()),
                    "offered_price": mar.offered_price,
                    "count": mar.count,
                    "product_id": product_id,
                    "product_name": product.name,
                    "brand_name": product.brand.name,
                    "is_attention": mar.is_attention(request.user.id)
                })

        return Response(resp)


class DetailTradingProductH5View(BaseAPIView):
    """
    产品挂单列表  发现/详情页/交易/
======

    GET     /product/tradings/:id/market-orders?action=addtime

URL参数
-----

    id:
        产品ID

Query参数
-------

    action:
        -addtime    按时间倒序
        -offered_price  按价格倒序
        want_buy_in         只显示意向是卖出的，并默认按时间倒序
        satisfy_ta      只显示意向是买入的，并默认按时间排序
    """
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        product_id = kwargs['id']
        action = request.GET.get("action", '-addtime')
        offset = request.GET.get('offset', -1)
        limit = request.GET.get('limit', -1)

        offset, limit = val(offset, limit)
        product = Product.objects.filter(id=product_id).first()
        if product == None:
            raise JsonAPIException(ErrCode.RETURN_EMPTY.name, ErrCode.RETURN_EMPTY.value)

        resp = {"count": 0, "trade_items": []}
        if limit == 0:
            return Response(resp)

        order_by = "-add_timestamp"
        intention_type = ""
        if action == "addtime":
            order_by = "add_timestamp"
        elif action == "-addtime":
            order_by = "-add_timestamp"
        elif action == "want_buy_in":
            intention_type = "BUY"
        elif action == "satisfy_ta":
            intention_type = "SELL"
        elif "offered_price" in action:
            order_by = action

        if intention_type == "":
            count, market_order = MarketOrder.objects.filter_by_page(offset, limit, status=MarketOrder.Status.ING.name,
                                                                     publish_type=MarketOrder.PublishType.MARKET.name,
                                                                     product_id=product_id,
                                                                     order=order_by, manzu_ta=False)
            resp['count'] = count
        else:
            count, market_order = MarketOrder.objects.filter_by_page(offset, limit, status=MarketOrder.Status.ING.name,
                                                                     publish_type=MarketOrder.PublishType.MARKET.name,
                                                                     intention_type=intention_type,
                                                                     product_id=product_id,
                                                                     order=order_by, manzu_ta=False)
            resp['count'] = count
        import json
        tpd = product.today_price_data
        wpd = product.week_price_data
        mpd = product.month_price_data

        resp.update({
            "product_id": product_id,
            "product_name": product.name,
            "brand_name": product.brand.name,
            "avg_price": product.avg_price_custom,
            "keeping_count": product.keeping_count,
            "up_down_percent": '%.2f%%' % (product.up_down_percent * 100),
            "up_down_percent_float": product.up_down_percent,
            "today_price_data": json.dumps(tpd),
            "week_price_data": json.dumps(wpd),
            "month_price_data": json.dumps(mpd),
        })

        print(tpd, wpd, mpd)

        pro = product
        repo = Repo.objects.filter(id=pro.repo_id)[0]
        images = ProductLongImage.objects.filter(product_id=pro.id).order_by("order")
        images_url = []
        for img in images:
            images_url.append({
                "img_url": img.banner_url
            })
        resp['product'] = {
            "logo": pro.logo,
            "name": pro.name,
            "brand_id": pro.brand.id,
            "brand": pro.brand.name,
            "brand_logo": pro.brand.logo,
            "brand_attention_count": pro.brand.attention_count,
            "store_id": pro.brand.store.id,
            "store": pro.brand.store.name,
            "stock": pro.stock,
            "pre_sale_price": pro.pre_sale_price,
            "id": pro.id,
            "video_banner": pro.video,
            "specification": pro.specification,
            "kind": pro.kind,
            "material": pro.material,
            "repo": pro.repo_id,
            "repo_name": repo.name,
            "age": pro.age,
            "publish_count": pro.publish_count,
            "technology": pro.technology,
            "tea_mountain": pro.tea_mountain,
            "altitude": pro.altitude,
            "ancient_tea_tree_count": pro.ancient_tea_tree_count,
            "year_avg_temperature": pro.year_avg_temperature,
            "year_avg_precipitation": pro.year_avg_precipitation,
            "made_in": pro.made_in,
            "long_images": images_url,
            "status": pro.status,
            "status_map": dict(Product.ProductStatus.get_choices()),
            "keeping_count": pro.keeping_count,
            "avg_price": pro.avg_price_custom,
            "up_down_percent": '%.2f%%' % (pro.up_down_percent * 100),
            "up_down_percent_float": pro.up_down_percent,
            "order_limit": NORMAL_USER_PRE_SALE_ORDER_LIMIT if not isinstance(request.user, User) else request.user.get_pre_sale_order_limit(pro.id),
        }

        store = Store.objects.filter(id=product.brand.store.id).first()
        resp['store'] = {
            "name": store.name,
            "store_type": store.store_type,
            "video_banner": store.video,
            "long_images": [
                {
                    "img_url": li.logo,
                }
                for li in StoreBanner.objects.filter(store=store).order_by('order')
            ],
            "store_type_map": {
                "GROWER": "茶农茶庄",
                "BRAND": "品牌茶庄"
            },
        }

        brand = Brand.objects.filter(id=product.brand.id).first()
        resp['brand'] = {
            'name': brand.name,
            'video_banner': brand.video,
            'long_images': [
                {'img_url': li.logo}
                for li in BrandLongImage.objects.filter(brand=brand).order_by('order')
            ]
        }

        for mar in market_order:
            users = User.objects.filter(id=mar.user_id)
            if users.count() > 0:
                user = users[0]
                resp['trade_items'].append({
                    "id": mar.id,
                    "user_id": mar.user_id,
                    "user_nickname": user.nickname,
                    "user_avatar": user.avatar,
                    "intention_type": mar.intention_type,
                    "intention_type_map": dict(MarketOrder.IntentionType.get_choices()),
                    "offered_price": mar.offered_price,
                    "count": mar.count,
                    "is_attention": mar.is_attention(request.user.id)
                })

        cmts = []
        # offset = request.GET.get('offset', -1)
        # limit = request.GET.get('limit', -1)
        # offset, limit = val(offset, limit)
        count, product_comments = ProductComment.objects.filter_by_page(-1, -1, product_id=pro.id)
        for p_com in product_comments:
            pics = ProductCommentPictures.objects.filter(product_comment_id=p_com.id).order_by("order")
            pictures = []
            for p in pics:
                pictures.append({
                    "img_url": p.picture
                })
            user = User.objects.filter(id=p_com.user_id).first()
            cmts.append({
                "user_id": p_com.user_id,
                "nickname": user.nickname,
                "user_avatar": user.avatar,
                "content": p_com.content,
                "add_time": time.strftime('%Y-%m-%d', time.localtime(p_com.add_timestamp)),
                "pictures": pictures,
            })
        resp['comments'] = cmts
        resp['download_link'] = APP_DOWNLOAD_LINK
        # return Response(resp)
        return render(request, 'system/FindDetails.html', resp)


class GetProductCommentListView(BaseAPIView):
    """
    产品评论列表
    ======
        GET     product/products/<str:id>/comments?offset=0&limit=20
        POST    product/products/<str:id>/comments
    URL参数
    -----
        id:
            产品ID

    Query参数
    -------
    offset：
        从第几个开始取得偏移量，第一页传0
    limit:
        每页获取条数
    """

    def get_permissions(self):
        # print(self.request.method)
        if self.request.method == 'GET':
            return []
        return [p() for p in self.permission_classes]

    def get(self, request, *args, **kwargs):
        product_id = kwargs["id"]
        offset = request.GET.get('offset', "")
        limit = request.GET.get('limit', "")

        offset, limit = val(offset, limit)
        resp = {}
        if limit == 0:
            resp['count'] = 0
            resp['items'] = []
            return Response(resp)

        # comm = ProductComment.objects.filter(product=product_id)
        count, product_comment = ProductComment.objects.filter_by_page(offset, limit, product_id=product_id)
        resp['count'] = count
        resp['items'] = []
        for p_com in product_comment:
            pics = ProductCommentPictures.objects.filter(product_comment_id=p_com.id).order_by("order")
            pictures = []
            for p in pics:
                pictures.append({
                    "img_url": p.picture
                })
            user = User.objects.filter(id=p_com.user_id).first()
            resp['items'].append({
                "user_id": p_com.user_id,
                "nickname": user.nickname,
                "user_avatar": user.avatar,
                "content": p_com.content,
                "add_time": time.strftime('%Y-%m-%d', time.localtime(p_com.add_timestamp)),
                "pictures": pictures,
            })
        return Response(resp, status=status.HTTP_200_OK)

    def post(self, request, *_, **kwargs):
        """
        发表评论
        {
            "content": "口感不错，下次还来",
            "pictures": [
               "id1", "id2"
            ]
        }
        """
        product = Product.objects.filter(id=kwargs.get('id', '')).first()
        if not product:
            raise ParametersErrorAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='产品不存在')
        # 判断评论是否有评论
        product_comment = ProductComment.objects.filter(product_id=kwargs.get('id', ''),
                                                        user_id=request.user.id).first()
        if product_comment:
            raise JsonAPIException(ErrCode.COMMENT_HAVE.name, ErrCode.COMMENT_HAVE.value)

        data = copy.copy(request.data)
        content = data.get('content', None).strip()
        if not content:
            raise ParametersErrorAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='评论内容不能为空')
        with transaction.atomic():
            pc = ProductComment.objects.create(user_id=request.user.id, product=product, content=content)
            pics = data.get('pictures',
                            [])  # ["5b98c27e2b694716b86895a397843c68","3abb6131cd4641c78a78940b87a1c5d5","fd5a658e2cf94e50826ae0603dc47fab"]

            if PublicFile.objects.filter(id__in=pics).count() != len(pics):
                print()
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='图片未完全上传')

            for idx, pfid in enumerate(pics):
                pcp = ProductCommentPictures.objects.create(
                    product_comment=pc,
                    picture_public_file_id=pfid,
                    order=idx
                )

        return Response({})


class PublishMarketOrderView(BaseAPIView):
    """
    发布挂单（买入卖出）信息
    """

    def _process_satisfy_ta(self, request, market_order: MarketOrder, goods_blocks, *args, **kwargs):
        user = request.user
        resp = {}
        intention_type = MarketOrder.IntentionType.SELL.name
        offered_price = is_Decimal(market_order.offered_price)
        count = goods_blocks.count()
        publish_type = MarketOrder.PublishType.MARKET.name
        as_gift = False
        as_gift_append_memo = None
        direct_to_user_mobile = None  # 手机号

        product = market_order.product
        direct_to_user_id = None

        with transaction.atomic():

            obj = MarketOrder.objects.create(
                user_id=user.id,
                product=product,
                offered_price=offered_price,
                count=count,
                publish_type=publish_type,
                intention_type=intention_type,
                status=MarketOrder.Status.ING.name,
                buy_in_market_order=market_order,
            )
            if as_gift:
                obj.as_gift = True
                obj.as_gift_append_memo = as_gift_append_memo
                obj.direct_to_user_id = direct_to_user_id
                obj.direct_to_user_mobile = direct_to_user_mobile
            else:
                obj.as_gift = False
                if publish_type == MarketOrder.PublishType.MARKET.name:
                    pass
                elif publish_type == MarketOrder.PublishType.DIRECTIONAL.name:
                    obj.direct_to_user_id = direct_to_user_id
                    obj.direct_to_user_mobile = direct_to_user_mobile
            obj.save()
            sell_market_order = obj
            sell_market_order.manzu_ta = True
            sell_market_order.save()

            repo_amount = 0
            # 处理区块哦
            for gb in goods_blocks:
                gb.market_order_id = sell_market_order.id
                gb.save()
                repo_amount += gb.get_block_detail()['repo_amount']

            order_amount = Decimal(market_order.offered_price * goods_blocks.count())

            # 计算优惠价格
            all_repo_preferential_amount = SystemSetting.get_repo_cost_preferential_amount(user, repo_amount)
            all_repo_real_pay_amount = repo_amount - all_repo_preferential_amount  # 实际支付仓储费

            # 计算手续费
            procedure = SystemSetting.get_procedure_preferential_amount(user, order_amount)
            procedure_real_pay_amount = procedure['procedure_real_pay_amount']

            # 存仓费+手续费 < 支付金额
            if Decimal(all_repo_real_pay_amount) + Decimal(procedure_real_pay_amount) > Decimal(order_amount):
                # sell_market_order.delete()
                raise JsonAPIException(ErrCode.MARKET_AMOUNT_EXCEPT.name, ErrCode.MARKET_AMOUNT_EXCEPT.value)

            market_order_id = sell_market_order.id
            resp['id'] = market_order_id

        msg = CreateMessageView.message(msg_type=Message.MsgType.WANT_BUY.name, oper_user=user,
                                        message_user_id=market_order.user_id,
                                        product_name=market_order.product.name, market_order_id=sell_market_order.id)
        getui = GetuiClient()
        to_user = User.objects.get(pk=market_order.user_id)
        if to_user.getui_clientid:
            pr = PushRecord.objects.create(
                user_id=to_user.id,
                message=msg,
                content=msg.make_transmission_msg(),
                send_type=PushRecord.SendType.TRANSMISSION.name,
            )
            status_code, rs = getui.push_single_transmission(
                cid=to_user.getui_clientid,
                transmission_content=msg.make_transmission_msg(),
                transmission_type=True
            )
            pr.provider_response_status_code = status_code
            pr.provider_response_data = rs
            pr.save()
        return Response(resp)

    def _process_publish(self, request, *args, **kwargs):
        from tuntun.settings import PROTOCOL, DOMAIN
        user = request.user
        re_data = request.data
        product_id = re_data["product_id"]
        intention_type = re_data["intention_type"]
        offered_price = is_Decimal(re_data["offered_price"])
        count = re_data["count"]
        publish_type = re_data["publish_type"]
        as_gift = re_data["as_gift"]
        as_gift_multiple = re_data.get('as_gift_multiple', False)
        as_gift_append_memo = re_data.get("as_gift_append_memo", None)
        direct_to_user_mobile = re_data.get("direct_to_user_id", None)  # 手机号
        goods_blocks = re_data.get("goods_blocks", [])

        if user.mobile == direct_to_user_mobile:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='不能指定出售或赠送给自己哦')

        # 基本检查
        if getattr(MarketOrder.PublishType, publish_type, None) is None:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='发布类型错误', status=400)
        if getattr(MarketOrder.IntentionType, intention_type, None) is None:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='意向类型错误', status=400)
        if as_gift not in [True, False]:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='是否赠送参数错误', status=400)

        product = Product.objects.get(pk=product_id)
        direct_to_user_id = None
        direct_to_user = None
        market_order = None

        market_order_id = ''
        resp = {'order_info': {}}

        if intention_type != MarketOrder.IntentionType.BUY.name:
            count = len(goods_blocks)
            if count == 0:
                raise JsonAPIException(ErrCode.PARAMETER_ERROR.name, "选择区块为空，请重新选择")

        with transaction.atomic():
            # 逻辑检查
            gbs = []
            if intention_type in [MarketOrder.IntentionType.SELL.name, ]:
                gbs = GoodsBlock.objects.filter(id__in=[g['id'] for g in goods_blocks]).exclude(
                    trade_type=GoodsBlock.TradeType.TAKE_OUT.name)
                if gbs.filter(~Q(market_order=None)):
                    raise JsonAPIException(code=ErrCode.MARKETORDER_TRADE.name, msg=ErrCode, status=400)

            if as_gift:
                if not as_gift_multiple:
                    direct_to_user, created = User.objects.get_or_create(mobile=direct_to_user_mobile)
                    if created:
                        direct_to_user.nickname = User.get_nickname()
                        direct_to_user.state = User.State.INACTIVE.name
                        direct_to_user.source = User.Source.BE_GIFTED.name
                        direct_to_user.save()
                    direct_to_user_id = direct_to_user.id
                else:
                    if not product.free_repo_cost:
                        raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='该产品不支持赠送多人')
                    direct_to_user = None
                    direct_to_user_id = None
            else:
                if publish_type == MarketOrder.PublishType.DIRECTIONAL.name:
                    direct_to_user = User.objects.filter(mobile=direct_to_user_mobile).first()
                    if not direct_to_user:
                        raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='定向用户不存在', status=400)
                    if direct_to_user.id == user.id:
                        raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='不能发送给自己', status=400)
                    direct_to_user_id = direct_to_user.id

            # 创建挂单
            market_order = MarketOrder(
                user_id=user.id,
                product=product,
                offered_price=Decimal(str(offered_price)),
                count=count,
                publish_type=publish_type,
                intention_type=intention_type,
                status=MarketOrder.Status.ING.name,
                buy_in_market_order=None,
            )
            # direct_to_user_mobile direct_to_user_id as_gift as_gift_append_memo
            if as_gift:
                if not as_gift_multiple:
                    market_order.as_gift = True
                    market_order.as_gift_multiple = False
                    market_order.as_gift_append_memo = as_gift_append_memo
                    market_order.direct_to_user_id = direct_to_user_id
                    market_order.direct_to_user_mobile = direct_to_user_mobile
                else:
                    market_order.as_gift = True
                    market_order.as_gift_multiple = True
                    market_order.as_gift_append_memo = as_gift_append_memo
                    market_order.direct_to_user_id = None
                    market_order.direct_to_user_mobile = None
            else:
                market_order.as_gift = False
                if publish_type == MarketOrder.PublishType.MARKET.name:
                    pass
                elif publish_type == MarketOrder.PublishType.DIRECTIONAL.name:
                    market_order.direct_to_user_id = direct_to_user_id
                    market_order.direct_to_user_mobile = direct_to_user_mobile
            market_order.save()

            # 赠送，特殊处理，除了生成挂单，还要生成订单
            if as_gift and not as_gift_multiple:
                order = Order.objects.create(
                    no=Order.make_order_no(user.mobile), amount=Decimal('0.00'),
                    payment_method=Order.PaymentMethod.ALI.name, status=Order.Status.CREATED.name,
                    expire_at=time.time() + PAY_EXPIRE_TIME, buyer_user_id=direct_to_user_id,
                    as_gift=True, as_gift_pre_pay_repo_cost=True,
                )
                # 子订单
                total_repo_cost = Decimal('0.00')
                total_as_gift_pre_pay_repo_cost_amount = Decimal('0.00')

                for gb in gbs:
                    repo = Repo.objects.get(pk=gb.repo_id)
                    sub_order = SubOrder(
                        order=order,
                        goods_block_id=gb.id,
                        product_id=product.pk,
                        product_name=product.name,
                        goods_block_repo_id=repo.pk,
                        goods_block_repo_name=repo.name,
                        store_unit_id=gb.store_unit_id,
                        price_per_100g_1d=gb.repo_cost_price_per_100g_1d,
                        amount=Decimal('0.00'),
                        seller_user_id=user.pk,
                        market_order_id=market_order.pk,
                        create_type=SubOrder.CreateType.MARKET_BUY_IN.name,
                        repo_cost_start_datetime=gb.trade_datetime,
                        repo_cost_end_datetime=datetime.datetime.now(),
                    )
                    sub_order.repo_amount = gb.repo_amount
                    sub_order.save()
                    total_repo_cost += sub_order.repo_amount
                    total_as_gift_pre_pay_repo_cost_amount += Decimal('2') * Decimal(gb.product.weight) * Decimal(gb.repo_cost_price_per_100g_1d)

                total_as_gift_pre_pay_repo_cost_amount = round(total_as_gift_pre_pay_repo_cost_amount, 2)

                order.repo_amount = total_repo_cost
                order.repo_preferential_amount = SystemSetting.get_repo_cost_preferential_amount(user, order.repo_amount)
                order.repo_real_pay_amount = order.repo_amount - order.repo_preferential_amount

                order.procedure_amount = Decimal('0.00')
                order.procedure_preferential_amount = Decimal('0.00')
                order.procedure_real_pay_amount = Decimal('0.00')

                order.logistics_amount = Decimal('0.00')
                order.logistics_preferential_amount = Decimal('0.00')
                order.logistics_real_pay_amount = Decimal('0.00')

                order.as_gift_pre_pay_repo_cost_amount = total_as_gift_pre_pay_repo_cost_amount
                order.amount = order.repo_real_pay_amount + order.as_gift_pre_pay_repo_cost_amount
                order.save()
                resp['order_info'] = {
                    'no': order.no,
                    'expire_at': order.expire_at,
                    'repo_amount': order.repo_amount.__str__(),
                    'pre_pay_repo_cost_amount': order.as_gift_pre_pay_repo_cost_amount.__str__(),
                    'repo_preferential_amount': order.repo_preferential_amount.__str__(),
                    'id': order.id,
                    'amount': order.amount.__str__(),
                }

            # 市场挂单，没关联买入订单
            if not market_order.as_gift and publish_type == MarketOrder.PublishType.MARKET.name and market_order.buy_in_market_order is None:
                t = task_match_market_order.delay(market_order.id)  # 发起异步任务自动匹配
                from apps.mix.models import TaskProcess
                TaskProcess.objects.create(task_callable="task_match_market_order",
                                           task_name=task_match_market_order.name, task_id=t.id)

            repo_amount = Decimal('0.00')
            # 处理区块哦
            gbcount = 0
            for gb in gbs:
                gb.market_order_id = market_order.id
                gb.save()
                repo_amount += gb.repo_amount
                gbcount += 1

            if market_order.intention_type == MarketOrder.IntentionType.SELL.name and as_gift == False:
                order_amount = Decimal(market_order.offered_price * gbcount)

                # 计算优惠价格
                all_repo_preferential_amount = SystemSetting.get_repo_cost_preferential_amount(user, repo_amount)
                all_repo_real_pay_amount = repo_amount - all_repo_preferential_amount  # 实际支付仓储费

                # 计算手续费
                procedure = SystemSetting.get_procedure_preferential_amount(user, order_amount)
                procedure_real_pay_amount = procedure['procedure_real_pay_amount']

                # 存仓费+手续费 < 支付金额
                if Decimal(all_repo_real_pay_amount) + Decimal(procedure_real_pay_amount) > Decimal(order_amount):
                    raise JsonAPIException(ErrCode.MARKET_AMOUNT_EXCEPT.name, ErrCode.MARKET_AMOUNT_EXCEPT.value)

            market_order_id = market_order.id
            resp['id'] = market_order_id

        if not as_gift and direct_to_user:
            msg = CreateMessageView.message(
                msg_type=Message.MsgType.WANT_BUY.name, oper_user=user,
                message_user_id=direct_to_user.id,
                product_name=market_order.product.name, market_order_id=market_order.id)
            getui = GetuiClient()
            to_user = direct_to_user
            if to_user.getui_clientid:
                pr = PushRecord.objects.create(
                    user_id=to_user.id,
                    message=msg,
                    content=json.dumps(msg.make_transmission_msg()),
                    send_type=PushRecord.SendType.TRANSMISSION.name,
                )
                push_info = {
                    "aps": {
                        "alert": {
                            "title": msg.title,
                            "body": msg.content,
                        },
                        "autoBadge": "+1",
                        "content-available": 1
                    },
                }
                status_code, rs = getui.push_single_transmission(
                    cid=to_user.getui_clientid,
                    transmission_content=msg.make_transmission_msg(),
                    transmission_type=True,
                    # push_info=push_info,
                )
                pr.provider_response_status_code = status_code
                pr.provider_response_data = rs
                pr.save()

        resp['as_gift_multiple_qr_code_url'] = '{protocol}://{domain}/pages/phoneShare.html?id={market_order_id}'.format(
            protocol=PROTOCOL,
            domain=DOMAIN,
            market_order_id=market_order.id)
        return Response(resp)

    def post(self, request, *args, **kwargs):
        data = copy.copy(request.data)
        market_order_id = data.get('market_id', None)
        if market_order_id:  # 满足TA
            market_order = MarketOrder.objects.filter(pk=market_order_id).first()
            if not market_order:
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='挂单不存在', status=400)
            goods_blocks = data.get('goods_blocks', [])
            goods_blocks_ids = [e['id'] for e in goods_blocks]
            gbs = GoodsBlock.objects.filter(market_order=None, owner_user_id=request.user.id,
                                            id__in=goods_blocks_ids).exclude(
                trade_type=GoodsBlock.TradeType.TAKE_OUT.name)
            if gbs.count() < len(goods_blocks_ids):  # 检查所选区块是不是允许卖
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='包含已挂单的产品唯一码', status=400)
            if gbs.count() > market_order.count:
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='所选数量超过对方需求的数量', status=400)

            return self._process_satisfy_ta(request, market_order, gbs, *args, **kwargs)
        else:  # 正常发布挂单
            return self._process_publish(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        """
        挂单列表/礼物赠送记录
        ===========
            GET     /product/market-orders?filter=gift
        Query参数
        -------

            filter:
                筛选条件 gift-礼物赠送记录  market-茶市互易 all-所有
        Response
        --------

            {
                "count": 10,
                "items":[
                    {
                        "id":   "market-order-id",
                        "order_id": "order-id",
                        "product_id": "product-id",
                        "product_name": "product-name",
                        "product_logo": "http://www.a.com/a.png",
                        "product_avg_price": 2000.00,
                        "up_down_percent": "+0.01",
                        "direct_to_user_mobile": "13311112222",
                        "direct_to_user_id": "direct-to-user-id",
                        "add_time": "2018.01.18 17:30",
                        "count": 2,
                        "status": "ING",
                        "status_map": {
                            "ING": "赠送中",
                            "END": "已送出"
                        }
                        "procedure_amount": 4.00,
                        "procedure_preferential_amount": 2.00,
                        "procedure_real_pay_amount": 2.00.
                        "repo_amount": 45.00,
                        "repo_preferential_amount": 4.00,
                        "repo_real_pay_amount": 41.00,
                        "logistics_amount": 10.00,
                        "logistics_preferential_amount": 2.00,
                        "logistics_real_pay_amount": 8.00
                        "payment_method": "ALI",
                        "payment_method_map": {
                            "ALI": "支付宝",
                            "WEIXIN": "微信",
                        }
                    },
                ]
            }

        :param request:
        :param args:
        :param kwargs:
        :return:
        """

        user = request.user

        filter = request.GET.get("filter")
        if filter == "gift":
            markets = MarketOrder.objects.filter(user_id=user.id, as_gift=True).exclude(
                status=MarketOrder.Status.CANCELED.name, deleted_at=0)
        else:
            markets = MarketOrder.objects.filter(user_id=user.id, as_gift=False).exclude(
                status=MarketOrder.Status.CANCELED.name, deleted_at=0)

        resp = {"count": markets.count(), "items": []}
        for market in markets:
            order_id = ""
            suborders = SubOrder.objects.filter(market_order_id=market.id)
            print(market.pk, suborders)
            first_sub_order = suborders.first()
            if not first_sub_order:
                order = None
            else:
                order = first_sub_order.order

            resp["items"].append({
                "id": market.id,
                "order_id": order.id if order else '',
                "product_id": market.product.id,
                "product_name": market.product.name,
                "product_logo": market.product.logo,
                "product_avg_price": market.product.avg_price_custom,
                "up_down_percent": '%.2f%%' % (market.product.up_down_percent * 100),
                "direct_to_user_mobile": market.direct_to_user_mobile,
                "direct_to_user_id": market.direct_to_user_id,
                "add_time": market.add_timestamp,
                "as_gift": market.as_gift,
                "as_gift_multiple": market.as_gift_multiple,
                "count": market.count,
                "status": market.status,
                "status_map": dict(MarketOrder.Status.get_choices()),
                "repo_amount": order.repo_amount if order else '0.00',
                "repo_preferential_amount": order.repo_preferential_amount if order else '0.00',
                "repo_real_pay_amount": order.repo_real_pay_amount if order else '0.00',
                "payment_method": "ALI",
                "payment_method_map": {
                    "ALI": "支付宝",
                    "WEIXIN": "微信",
                }
            })

        return Response(resp)


class DetailMarketOrderView(BaseAPIView):
    """
    获取挂单详情/赠送详情 (出售/产品互易/产品唯一码/发布发现)(出售/指定用户/输入手机号)
    ===================

    GET     /product/orders/:id/blocks

    """

    def get(self, request, *args, **kwargs):
        user = request.user
        product_id = kwargs["id"]

        try:
            offset = int(request.GET.get('offset', 0))
            limit = int(request.GET.get('limit', 15))
        except:
            offset = 0
            limit = 15

        goods = GoodsBlock.objects.filter(~Q(trade_type=GoodsBlock.TradeType.TAKE_OUT.name), owner_user_id=user.id, product_id=product_id, market_order_id=None)

        count, objs = self.process_page(goods, offset, limit)

        resp = {"count": count, "items": []}
        for good in objs:
            resp["items"].append(good.get_block_detail())
        return Response(resp)


class GetMessageMarketOrderView(BaseAPIView):
    """
    我的/消息通知/求TA/详情
    我的/消息通知/被赠送/是否接受
    =================

        GET     /product/market-orders/:id

    URL参数
    -----

        id:
            挂单ID

    """

    def get(self, request, *args, **kwargs):
        market_id = kwargs["id"]
        type = request.GET.get("type")

        market = MarketOrder.objects.filter(id=market_id).first()
        sub_orders = SubOrder.objects.filter(market_order_id=market.id)

        if market.status == 'ING' or market.status == 'TRADE':
            blocks = GoodsBlock.objects.filter(market_order_id=market_id)
        else:
            blocks = GoodsBlock.objects.filter(id__in=[so.goods_block_id for so in sub_orders])

        price = market.offered_price
        if type == "buy":
            price = market.offered_price
        elif type == "gift":
            price = market.product.last_trade_price

        sell_user_nickname = ""
        sell_user = User.objects.filter(id=market.user_id).first()
        if sell_user:
            sell_user_nickname = sell_user.nickname

        buyer_user_nickname = ""
        if market.related_order:
            buyer_user = User.objects.get(pk=market.related_order.buyer_user_id)
            buyer_user_nickname = buyer_user.nickname

        repo_items = []
        if blocks.count() > 0:
            blocks.first().repo_list()

        resp = {
            "id": market_id,
            "product": market.product.name,
            "product_logo": market.product.logo,
            "brand": market.product.brand.name,
            "price": price,
            "count": market.count,
            "seller_user_id": sell_user.id,
            "sell_user_name": sell_user_nickname,
            "buyer_user_name": buyer_user_nickname,
            "blocks": [],
            "repos": repo_items,
            "direct_to_user_mobile": market.direct_to_user_mobile,
            "gift_out_datetime": market.gift_out_datetime,
            "gift_accept_datetime": market.gift_accept_datetime,
            "as_gift": market.as_gift,
            "as_gift_multiple": market.as_gift_multiple,
            "picked_count": SubOrder.objects.filter(market_order_id=market.id).count(),
            "status": market.status,
            "status_display": getattr(MarketOrder.Status, market.status).value,
            "publish_type": market.publish_type,
            "publish_type_map": dict(MarketOrder.PublishType.get_choices())
        }

        related_order = market.related_order
        try:
            if related_order:
                resp['order_info'] = {
                    "id": related_order.id,
                    "repo_amount": related_order.repo_amount,
                    "as_gift_pre_pay_repo_cost_amount": related_order.as_gift_pre_pay_repo_cost_amount,
                    "repo_preferential_amount": related_order.repo_preferential_amount,
                    "amount": related_order.amount,
                    "payment_method_display": getattr(Order.PaymentMethod, related_order.payment_method).value,
                    "procedure_amount": related_order.procedure_amount,
                    "procedure_preferential_amount": related_order.procedure_preferential_amount,
                    "procedure_real_pay_amount": related_order.procedure_real_pay_amount,
                    "to_seller_user_amount": related_order.to_seller_user_amount,
                    "trade_datetime": related_order.trade_datetime,
                    "amount_to_display": "账户余额",
                    "status": related_order.status,
                    "status_map": dict(Order.Status.get_choices())
                }

            for block in blocks:
                resp["blocks"].append(block.get_block_detail())
        except:
            # res = {
            #     'code': 'PARAMETER_ERROR',
            #     'msg': '此单正在支付中',
            #     'errors': [traceback.format_exc(), ]
            # }
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='此单正在支付中', errors=[traceback.format_exc(),])

        return Response(resp)

    post = get

class GetMessageBuyOrderView(BaseAPIView):
    """
    我的/消息通知/已买预售详情
    product/buy-orders/<str:id>
    """

    def get(self, request, *args, **kwargs):
        order_id = kwargs["id"]
        resp = {}
        order = Order.objects.filter(id=order_id).first()
        suborders = SubOrder.objects.filter(order_id=order_id)

        try:
            offset = int(request.GET.get('offset', 0))
            limit = int(request.GET.get('limit', 15))
        except:
            offset = 0
            limit = 15

        count, objs = self.process_page(suborders, offset, limit)

        suborder = suborders.first()
        block = GoodsBlock()
        block_items = []
        for sub in objs:
            block = GoodsBlock.objects.filter(id=sub.goods_block_id).first()
            block_items.append(block.get_block_detail())

        sell_nickname = ""
        if suborder.create_type != SubOrder.CreateType.PRE_SALE_BUY_IN.name:
            sell_nickname = User.objects.filter(id=suborder.seller_user_id).first().nickname

        order_product = Product.objects.get(pk=suborder.product_id)
        resp = {
            "product_id": order_product.id,
            "product_name": order_product.name,
            "product_image": order_product.logo,
            "brand_name": order_product.brand.name,
            "buy_count": suborders.count(),
            "buy_price": order.amount,
            "up_down_percent": '%.2f%%' % (order_product.up_down_percent * 100),
            "block_items": block_items,
            "amount": order.amount,
            "payment": order.payment_method,
            "payment_map": dict(Order.PaymentMethod.get_choices()),
            "create_type": suborder.create_type,
            "create_type_map": dict(SubOrder.CreateType.get_choices()),
            "trade_datetime": '%s %s' % (suborder.repo_cost_end_datetime.strftime('%Y.%m.%d'),
                                         suborder.repo_cost_end_datetime.strftime('%H:%M')),
            "sell_nickname": sell_nickname
        }

        return Response(resp)


class GetDetailMessageBuyOrderView(BaseAPIView):
    """
    我的/消息通知/已买明細
    product/buy-orders/block/<str:id>
    """

    def get(self, request, *args, **kwargs):
        block_id = kwargs["id"]
        block = GoodsBlock.objects.filter(id=block_id).first()
        resp = block.get_block_detail()
        return Response(resp)


class DetailMarketBuyOrderView(BaseAPIView):
    """
    买入/选择产品
===================

    GET     /product/market-orders/:id/blocks

    """

    def get(self, request, *args, **kwargs):
        market = MarketOrder.objects.filter(id=kwargs["id"]).first()
        if market:
            if market.status == MarketOrder.Status.ING.name:
                goods = GoodsBlock.objects.filter(market_order_id=kwargs["id"])
                repo_items = []
                if goods.count() > 0:
                    repo_items = goods.first().repo_list()
                resp = {
                    "count": goods.count(),
                    "items": [],
                    "repo_items": repo_items
                }
                for good in goods:
                    resp["items"].append(good.get_block_detail())
            else:
                raise JsonAPIException(ErrCode.MARKETORDER_NULL.name, ErrCode.MARKETORDER_NULL.value)
        else:
            raise JsonAPIException(ErrCode.MARKETORDER_NULL.name, ErrCode.MARKETORDER_NULL.value)

        return Response(resp)


class GetDirectionalSellView(BaseAPIView):
    """
    满足TA详情(满足TA/选择产品/)
===================

    GET     /product/directional/:id/blocks

URL参数
-----

    id:
        MarketOrderId

    """

    def get(self, request, *args, **kwargs):
        user = request.user
        market_order_id = kwargs["id"]
        market_order = MarketOrder.objects.filter(id=market_order_id).first()
        if market_order.status != MarketOrder.Status.ING.name:
            raise JsonAPIException(ErrCode.MARKETORDER_NULL.name, ErrCode.MARKETORDER_NULL.value)

        try:
            offset = int(request.GET.get('offset', 0))
            limit = int(request.GET.get('limit', 15))
        except:
            offset = 0
            limit = 15

        product_id = market_order.product.id
        goods = GoodsBlock.objects.filter(product_id=product_id, owner_user_id=user.id, market_order_id__isnull=True,
                                          trade_type__in=(GoodsBlock.TradeType.PRE_SALE.name,
                                                          GoodsBlock.TradeType.MARKET.name))
        count, objs = self.process_page(goods, offset, limit)

        repo_items = []
        if goods.count() > 0:
            goods.first().repo_list()

        resp = {
            "product_id": product_id,
            "product_name": market_order.product.name,
            "product_image": market_order.product.long_image(),
            "brand_name": market_order.product.brand.name,
            "buy_user": market_order.user_id,
            "price": market_order.offered_price,
            "count": count,
            "items": [],
            "repo_items": repo_items
        }

        for good in objs:
            resp["items"].append(good.get_block_detail())
        return Response(resp)


class GetTeaRepoBlocksListView(BaseAPIView):
    """
     我的藏茶/详情页
    GET     /product/tea-repo/:id/blocks?action=take_out
    """

    def get(self, request, *args, **kwargs):
        user = request.user
        product_id = kwargs["id"]
        action = request.GET.get('action')

        try:
            limit = int(request.GET.get('limit', -1))
            offset = int(request.GET.get('offset', -1))
        except:
            limit = -1
            offset = -1

        goods = GoodsBlock.objects.filter(owner_user_id=user.id, product_id=product_id)

        goods_ids = [g.id for g in goods]

        if action == 'take_out':
            goods = goods.filter(market_order=None, taken_out=False)
        else:
            taken_out_gbs_ids = [e.goods_block_id for e in SubOrder.objects.filter(product_id=product_id, create_type=SubOrder.CreateType.TAKE_OUT.name, order__status=Order.Status.FINISHED.name)]
            goods = goods.exclude(id__in=taken_out_gbs_ids)

        count = goods.count()
        objs = []
        if offset == -1 and limit == -1:
            objs = goods
        else:
            try:
                paginator = Paginator(goods, limit)
                req_page = offset // limit + 1
                objs = paginator.page(req_page).object_list
            except:
                count = 0
                objs = []

        resp = {"count": count, "items": []}
        for good in objs:
            resp["items"].append(good.get_block_detail())
        return Response(resp)


class GetTeaRepoBlocksDetailView(BaseAPIView):
    """
    我的藏茶/详情页/明细
===================
    GET     /product/tea-repo/blocks/:id/detail

    """

    def get(self, request, *args, **kwargs):
        good_block = GoodsBlock.objects.filter(id=kwargs["id"]).first()
        resp = {}
        if good_block:
            resp = good_block.get_block_detail()

        return Response(resp)


class GetPackageListView(BaseAPIView):
    """
    获取产品包装
    GET     /product/package/:id

    ["26adca00dd6d4673818e528d9b5ceb97", "16e2ea5fa7354cd6a7f16e4d37207169"]
    ["d29f6a696dbb422595282c70be1a4da7", "d29f6a696dbb422595282c70be1a4da6", "d29f6a696dbb422595282c70be1a4da3", "3a44bed789a24aef84e76a564b2c737f"]

    """

    def get(self, request, *args, **kwargs):
        product_id = kwargs["id"]
        product = Product.objects.filter(id=product_id).first()
        packages = Package.objects.filter(id__in=product.package_ids)
        resp = {}
        for package in packages:
            resp.append({
                "id": package.id,
                "name": package.name,
                "price": package.price,
                "avatar": package.avatar,
                "brand": product.brand.name
            })
        return Response(resp)


class AddUserAttentionBrandView(BaseAPIView):
    """
    关注品牌
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        brand_id = kwargs["id"]
        brand = Brand.objects.filter(id=brand_id).first()
        if brand:
            if UserAttentionBrand.objects.filter(user_id=user.id, brand_id=brand).count() > 0:
                raise JsonAPIException(ErrCode.ATTENTION_HAVE.name, ErrCode.ATTENTION_HAVE.value)
            re = UserAttentionBrand.objects.create(user_id=user.id, brand_id=brand)
        return Response({"id": re.id, "count": re.att_count})


class CancelUserAttentionBrandView(BaseAPIView):
    """
    取消关注品牌
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        brand_id = kwargs["id"]
        att_brand = UserAttentionBrand.objects.filter(user_id=user.id, brand_id_id=brand_id).delete()
        att_count = UserAttentionBrand.objects.filter(brand_id=brand_id).count()
        return Response({"code": "ok", "count": att_count})


class GetUserAttentionBrandView(BaseAPIView):
    """
    我的/品牌关注
    /product/user/brands/list
    """

    def get(self, request, *args, **kwargs):
        user = request.user
        attentions = UserAttentionBrand.objects.filter(user_id=user.id)

        resp = []
        for attention in attentions:
            resp.append({
                "id": attention.brand_id.id,
                "name": attention.brand_id.name,
                "logo": attention.brand_id.logo,
                "count": attention.att_count,
            })
        return Response(resp)


class AddUserAttentionProductView(BaseAPIView):
    """
    关注产品
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        product_id = kwargs["id"]
        if UserAttentionProduct.objects.filter(user_id=user.id, product_id_id=product_id).count() > 0:
            raise JsonAPIException(ErrCode.COLLECTED.name, ErrCode.COLLECTED.value)
        att_product = UserAttentionProduct.objects.create(user_id=user.id, product_id_id=product_id)
        return Response({"id": att_product.id, "count": att_product.att_count})


class CancelUserAttentionProductView(BaseAPIView):
    """
    取消关注产品
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        product_id = kwargs["id"]
        att_product = UserAttentionProduct.objects.filter(user_id=user.id, product_id_id=product_id).delete()
        att_count = UserAttentionProduct.objects.filter(product_id_id=product_id).count().__str__()
        return Response({"code": "ok", "count": att_count})


class GetUserAttentionProductView(BaseAPIView):
    """
    我的/商品收藏/产品
    """

    def get(self, request, *args, **kwargs):
        user = request.user
        attentions = UserAttentionProduct.objects.filter(user_id=user.id)

        resp = []
        for attention in attentions:
            resp.append({
                "id": attention.product_id.id,
                "name": attention.product_id.name,
                "price": attention.product_id.pre_sale_price,
                "avg_price": attention.product_id.avg_price_custom,
                "status": attention.product_id.status,
                "status_map": dict(Product.ProductStatus.get_choices()),
                "up_down_percent": '%.2f%%' % (attention.product_id.up_down_percent * 100),
                "keeping_count": attention.product_id.keeping_count,
            })
        return Response(resp)


class AddUserCollectMarketOrderView(BaseAPIView):
    """
    关注交易
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        market_id = kwargs["id"]
        if UserCollectMarketOrder.objects.filter(user_id=user.id, market_order_id=market_id).count() > 0:
            raise JsonAPIException(ErrCode.COLLECTED.name, ErrCode.COLLECTED.value)
        re = UserCollectMarketOrder.objects.create(user_id=user.id, market_order_id=market_id)
        return Response({"id": re.id})


class CancelUserCollectMarketOrderView(BaseAPIView):
    """
    取消关注交易
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        market_id = kwargs["id"]
        UserCollectMarketOrder.objects.filter(user_id=user.id, market_order_id=market_id).delete()
        return Response({"code": "ok"})


class GetUserCollectMarketOrderView(BaseAPIView):
    """
    交易列表
    """

    def get(self, request, *args, **kwargs):
        user = request.user
        attentions = UserCollectMarketOrder.objects.filter(user_id=user.id)

        resp = []
        for attention in attentions:
            trade_user = User.objects.filter(id=attention.market_order.user_id).first()
            status_map = {"BUY": "满足Ta", "SELL": "买入", "END": "已失效"}
            status = "END"
            if attention.market_order.status == MarketOrder.Status.ING.name:  # 已失效
                status = attention.market_order.intention_type

            resp.append({
                "id": attention.market_order.id,
                "nickname": trade_user.nickname,
                "avatar": trade_user.avatar,
                "count": attention.market_order.count,
                "price": attention.market_order.offered_price,
                "status": status,
                "status_map": status_map,
            })
        return Response(resp)


class MarketOrderCancelView(BaseAPIView):
    """
    取消挂单
    """

    def post(self, request, *args, **kwargs):
        id = request.data['id']

        with transaction.atomic():
            market = MarketOrder.objects.filter(id=id).first()
            if market.status == MarketOrder.Status.TRADE.name:
                raise JsonAPIException(ErrCode.MARKETORDER_TRADEING.name, ErrCode.MARKETORDER_TRADEING.value)
            elif market.status == MarketOrder.Status.ING.name and market.as_gift_multiple:
                if SubOrder.objects.filter(market_order_id=market.id):
                    raise JsonAPIException(ErrCode.PARAMETER_ERROR.name, msg='该礼物已有人领取，无法取消')

            goods = GoodsBlock.objects.filter(market_order_id=id)
            for good in goods:
                good.market_order = None
                good.save()

            market.status = MarketOrder.Status.CANCELED.name
            market.save()
        return Response({})


class MarketOrderEditView(BaseAPIView):
    """
    编辑挂单
    """

    def post(self, request, *args, **kwargs):
        data = copy.copy(request.data)
        market_id = data['market_id']
        offered_price = is_Decimal(data['offered_price'])
        goods_blocks = data.get('goods_blocks', [])

        goods_blocks_ids = [e['id'] for e in goods_blocks]
        new_goods = GoodsBlock.objects.filter(market_order=None, owner_user_id=request.user.id,
                                              id__in=goods_blocks_ids)
        if new_goods.count() == 0:
            raise JsonAPIException(ErrCode.PARAMETER_EMPTY.name, ErrCode.PARAMETER_ERROR.value)

        with transaction.atomic():
            market = MarketOrder.objects.filter(id=market_id).first()
            if not market:
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='挂单不存在', status=400)
            if market.status == MarketOrder.Status.TRADE.name:
                raise JsonAPIException(ErrCode.MARKETORDER_TRADEING.name, ErrCode.MARKETORDER_TRADEING.value)

            market.offered_price = offered_price
            market.save()
            # 清空旧区块挂单信息
            old_goods = GoodsBlock.objects.filter(market_order_id=id)
            for good in old_goods:
                good.market_order = None
                good.save()

            # 添加新挂单区块信息
            for new_good in new_goods:
                new_good.market_order = market_id
                new_good.save()

        return Response({})


class RefuseMarketOrderView(BaseAPIView):
    """
    拒绝购买
    """

    def post(self, request, *args, **kwargs):
        id = kwargs["id"]
        market = MarketOrder.objects.filter(id=id).first()
        market.buy_in_market_order = None
        market.save()
        return Response({})
